package cn.zyl.demo.common.tools;

import cn.zyl.demo.common.exception.ToolsException;

import java.util.*;

/**
 * StringTool类说明:字符串工具类
 *
 * @author wsz
 * @version v1.0
 * @date 2020-07-22
 */
public class StringTool {
    private StringTool(){throw new IllegalAccessError("StringTool");}
    /** 空字符串数组*/
    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    /**
     * 如果给定字符串非空，则返回该字符串；否则返回空字符串。
     */
    public static String nullToEmpty(String string) {
        return (string == null) ? "" : string;
    }

    /**
     * 如果给定字符串非空，则返回该字符串；否则返回{@code null}。
     */
    public static String emptyToNull(String string) {
        return isNullOrEmpty(string) ? null : string;
    }

    /**
     * 如果给定字符串为null或为空字符串，则返回{@code true}。
     */
    public static boolean isNullOrEmpty(String str) {
        return str == null || str.length() == 0;
    }

    /**
     * 检查字符串是空白、空（“”）还是null。
     *
     * Strings.isBlank(null)      = true
     * Strings.isBlank("")        = true
     * Strings.isBlank(" ")       = true
     * Strings.isBlank("bob")     = false
     * Strings.isBlank("  bob  ") = false
     */
    public static boolean isBlank(String str) {
        int strLen;
        if (str != null && (strLen = str.length()) != 0) {
            for (int i = 0; i < strLen; i++) {
                if (!Character.isWhitespace(str.charAt(i))) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 检查字符串是否不为空（“”）、不为null且仅限空白。
     *
     * Strings.isNotBlank(null)      = false
     * Strings.isNotBlank("")        = false
     * Strings.isNotBlank(" ")       = false
     * Strings.isNotBlank("bob")     = true
     * Strings.isNotBlank("  bob  ") = true
     */
    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    /**
     * 将提供的文本拆分为数组，指定分隔符。
     * 空输入字符串返回null。
     * Strings.split(null, *)         = null
     * Strings.split("", *)           = []
     * Strings.split("a.b.c", '.')    = ["a", "b", "c"]
     * Strings.split("a..b.c", '.')   = ["a", "b", "c"]
     * Strings.split("a:b:c", '.')    = ["a:b:c"]
     * Strings.split("a b c", ' ')    = ["a", "b", "c"]
     */
    public static String[] split(String str, char separator) {
        return split(str, separator, false);
    }

    /**
     *将提供的文本拆分为数组，指定分隔符，如果{@code}为true，则保留所有标记，包括创建的空标记 通过相邻的分离器。
     * 空输入字符串返回null。
     * Strings.split(null, *, true)         = null
     * Strings.split("", *, true)           = []
     * Strings.split("a.b.c", '.', true)    = ["a", "b", "c"]
     * Strings.split("a..b.c", '.', true)   = ["a", "", "b", "c"]
     * Strings.split("a:b:c", '.', true)    = ["a:b:c"]
     * Strings.split("a b c", ' ', true)    = ["a", "b", "c"]
     * Strings.split("a b c ", ' ', true)   = ["a", "b", "c", ""]
     * Strings.split("a b c  ", ' ', true)  = ["a", "b", "c", "", ""]
     * Strings.split(" a b c", ' ', true)   = ["", a", "b", "c"]
     * Strings.split("  a b c", ' ', true)  = ["", "", a", "b", "c"]
     * Strings.split(" a b c ", ' ', true)  = ["", a", "b", "c", ""]
     */
    public static String[] split(String str, char separator, boolean preserveAllTokens) {
        if (str == null) { return null; }
        int len = str.length();
        if (len == 0) { return EMPTY_STRING_ARRAY; }
        List<String> list = new ArrayList<>();
        int i = 0, start = 0;
        boolean match = false;
        boolean lastMatch = false;
        while (i < len) {
            if (str.charAt(i) == separator) {
                if (match || preserveAllTokens) {
                    list.add(str.substring(start, i));
                    match = false;
                    lastMatch = true;
                }
                start = ++i;
                continue;
            }
            lastMatch = false;
            match = true;
            i++;
        }
        if (match || (preserveAllTokens && lastMatch)) {
            list.add(str.substring(start, i));
        }
        return list.toArray(new String[0]);
    }
    /**
     * <p>检查CharSequence是空的（“”）还是null。</p>
     * <pre>
     * StringUtils.isEmpty(null)      = true
     * StringUtils.isEmpty("")        = true
     * StringUtils.isEmpty(" ")       = false
     * StringUtils.isEmpty("bob")     = false
     * StringUtils.isEmpty("  bob  ") = false
     * </pre>
     * <p>注意：这个方法在Lang版本2.0中发生了变化。它不再修剪字符序列。该功能在isBlank（）中可用。</p>
     * @param cs  要检查的CharSequence可能为空
     * @return {@code true} 如果CharSequence为空或null
     * @since 3.0 已将签名从isEmpty（String）更改为isEmpty（CharSequence）
     */
    public static boolean isEmpty(final CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * <p>检查CharSequence是否不为空（“”）且不为null。</p>
     * <pre>
     * StringUtils.isNotEmpty(null)      = false
     * StringUtils.isNotEmpty("")        = false
     * StringUtils.isNotEmpty(" ")       = true
     * StringUtils.isNotEmpty("bob")     = true
     * StringUtils.isNotEmpty("  bob  ") = true
     * </pre>
     */
    public static boolean isNotEmpty(final CharSequence cs) {
        return !isEmpty(cs);
    }

    /**
     * 校验字符串长度
     * @param cs 字符串
     * @param minLen 预期最小长度
     * @param maxLen 预期最大长度
     * @return true 校验通过；false 校验不通过
     */
    public static boolean checkLength(final CharSequence cs , int minLen,int maxLen){
        ToolsException.isTrueThrow(minLen < 1,"min length less than 1./小于1");
        ToolsException.isTrueThrow(maxLen < minLen,"max length less than min length./max 小于 min");
        return !isEmpty(cs) && cs.length() >= minLen && cs.length() <= maxLen;
    }
    /** 生成 N 位随机数，包含数字和字符
     * @param charsCount 个数
     * @return 随机字符
     */
    public static String genRandomChars(int charsCount) {
        //排除易混淆的 0 O   1 l I  2 Z
        String[] beforeShuffle = new String[] { "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G"
                , "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y" };
        List<String> list = Arrays.asList(beforeShuffle);
        Collections.shuffle(list);
        StringBuilder sb = new StringBuilder();
        for (Object o : list) {
            sb.append(o);
        }
        return sb.toString().substring(0, charsCount);
    }

    /**
     * 生成随机密码，大小写字母、数字、标点符号
     * @param length 密码长度
     * @return 随机密码
     */
    public static String genRandomPass(int length){
        length = length < 0 ? 8 : length;
        StringBuilder sb = new StringBuilder();
        //符号
        char[] chars = new char[]{'!','#','$','%','&','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[',']'
            ,'^','_','`','{','|','}','~'};
        for(int i=0;i<length;i++){
            int f = (int) (Math.random()*4);
            double random = Math.random();
            if(f==0) {
                sb.append((char) ('A' + random * 26));
            }else if(f==1) {
                sb.append((char) ('a' + random * 26));
            }else if(f==2) {
                sb.append(chars[(int) (random * 29)]);
            }else {
                sb.append((char) ('0' + random * 10));
            }
        }
        return sb.toString();
    }
    /**
     * 首字母大写
     * @param str 内容
     * @return 结果
     */
    public static String firstUpper(String str) {
        if (str == null || "".equals(str.trim())) { return str; }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
    /**
     * 生成uuid，无“-”
     * @return uuid
     */
    public static String uuid() {
        return UUID.randomUUID().toString().replace("-", "");
    }
    public static void main(String[] args) {
        System.out.println("split(\"a b c \", ' ', true):"+Arrays.asList(split("a b c ", ' ', true)));
        System.out.println("split(\"a..b.c\", '.', true):"+Arrays.asList(split("a..b.c", '.', true)));
        System.out.println("split(\"a..b.c\", '.'):"+Arrays.asList(split("a..b.c", '.')));
        System.out.println("随机字符 15: "+genRandomChars(15));
        System.out.println("随机密码 24: "+genRandomPass(24));
        System.out.println("isNotEmpty(\" \"):"+isNotEmpty(" "));
        System.out.println("isNotBlank(\" \"):"+isNotBlank(" "));
        System.out.println(checkLength("1321", 2, 4));
        System.out.println(checkLength("1321", 4, 4));
    }
}
